package controller;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import model.Model;

import org.ini4j.Ini;
import org.ini4j.InvalidFileFormatException;
import org.ini4j.Profile.Section;

/**
 * Servlet implementation class Controller
 */
public abstract class Controller extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
	protected abstract Class<?> getClassModel();
	
	protected abstract String getPathConfig();
	
    protected Model preencheObjeto(Model model, HttpServletRequest request) {
    	
    	try {

			Class<?> cls = getClassModel();

			Field[] fields = cls.getDeclaredFields();

			Field field = null;
			
			String fieldName = null;
			
			Object fieldValue = null;
			
			String methodName = null;

			Method method = null;
			
			if (! request.getParameter("id").equals("")) {
				model.setId(request.getParameter("id"));
			} else {
				model.setId(request.getParameter("sectionType"));
			}
			

			for (int i = 0; i < fields.length; i++) {

				field = fields[i];

				fieldName = field.getName();
				
				fieldValue = request.getParameter(fieldName);
				
				if (fieldValue != null && fieldValue != "") {
				
					methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
	
					method = cls.getMethod(methodName, field.getType());
					
					method.invoke(model, fieldValue);
				}
			}
			
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	return model;
    }
    
    protected void insertConfig(Model model) {
    	try {
    		
    		File f = new File(getPathConfig());
		
			BufferedReader in = new BufferedReader(new FileReader(f));
    	
			Ini conf = new Ini();
			conf.load(in);
			
			Section section = conf.get(model.getId());
			
			if (section != null) {
				conf.remove(section);
				conf.add(model.getId());
				section = conf.get(model.getId());
			}
			
			Class<?> cls = getClassModel();

			Field[] fields = cls.getDeclaredFields();

			Field field = null;
			
			String fieldName = null;
			
			Object fieldValue = null;
			
			String methodName = null;

			Method method = null;
			
			for (int i = 0; i < fields.length; i++) {
				
				field = fields[i];

				fieldName = field.getName();
				
				if (fieldName.matches("id") || fieldName.indexOf("GUI") != -1) {
					continue;
				}
				
				methodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
				
				method = cls.getMethod(methodName);
				
				fieldValue = method.invoke(model);
				
				if (fieldValue == null) {
					continue;
				}
				
				//section.add(fieldName.toLowerCase(), fieldValue);
				section.put(fieldName.toLowerCase(), fieldValue);
			}
			
			File f2 = new File(getPathConfig().replace(".conf", "_temp.conf"));
			
			conf.store(f2);
			
			System.out.println(conf);
			
			f.delete();
			
			f2.renameTo(f);
			
    	} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidFileFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    protected void create(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		
		try {
			Class<?> classe = getClassModel();

			Model model = Model.getModelInstance(classe);

			this.preencheObjeto(model, request);

			this.insertConfig(model);

		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

    protected Model retrieve(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
    	
    	Model model = null;
    	
    	try {
			String id = request.getParameter("id");

			File f = new File(getPathConfig());

			BufferedReader in = new BufferedReader(new FileReader(f));

			Ini conf = new Ini();
			conf.load(in);

			Section section = conf.get(id);

			Class<?> cls = getClassModel();

			model = Model.getModelInstance(cls);
			
			model.setId(id);

			Field[] fields = cls.getDeclaredFields();

			Field field = null;

			String fieldName = null;

			Object fieldValue = null;

			String methodName = null;

			Method method = null;

			for (int i = 0; i < fields.length; i++) {

				field = fields[i];

				fieldName = field.getName();

				fieldValue = section.get(fieldName.toLowerCase());
				
				fieldValue = fieldValue == null ? null : ((String)fieldValue).replace("\"", "");

				if (fieldValue != null) {

					methodName = "set"
							+ fieldName.substring(0, 1).toUpperCase()
							+ fieldName.substring(1);

					method = cls.getMethod(methodName, field.getType());

					method.invoke(model, fieldValue);
				}
			}
    	} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	return model;
	}

    protected void update(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

	}

    protected void delete(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
    	
    	try {
    		
    		Class<?> classe = getClassModel();

			Model model = Model.getModelInstance(classe);
    		
    		File f = new File(getPathConfig());
		
			BufferedReader in = new BufferedReader(new FileReader(f));
    	
			Ini conf = new Ini();
			conf.load(in);
			
			Section section = conf.get(model.getId());
			
			conf.remove(section);
			
			File f2 = new File(getPathConfig().replace(".conf", "_temp.conf"));
			
			conf.store(f2);
			
			System.out.println(conf);
			
			f.delete();
			
			f2.renameTo(f);
			
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    	
    	

	}
    
    protected ArrayList<Model> listConfig() {
    	
    	ArrayList<Model> lista = new ArrayList<Model>(0);
    	
		try {

			File f = new File(getPathConfig());

			BufferedReader in = new BufferedReader(new FileReader(f));

			Ini conf = new Ini();
			conf.load(in);
			
			Class<?> cls = getClassModel();

			Model model = Model.getModelInstance(cls);
			
			Field[] fields = cls.getDeclaredFields();

			Field field = null;
			
			String fieldName = null;
			
			Object fieldValue = null;
			
			String methodName = null;

			Method method = null;
			
			Section section = null;
			
			for (String sectionName: conf.keySet()) {
				
				section = conf.get(sectionName);
				
				model = Model.getModelInstance(cls);
				
				model.setId(sectionName);
				
				for (int i = 0; i < fields.length; i++) {
					
					field = fields[i];

					fieldName = field.getName();
					
					fieldValue = section.get(fieldName.toLowerCase());
					
					if (fieldValue != null) {
					
						methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
		
						method = cls.getMethod(methodName, field.getType());
						
						method.invoke(model, fieldValue);
					}
				}
				
				lista.add(model);
	    	}

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidFileFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return lista;
    }
    
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected abstract void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doGet(request, response);
	}

}
